/**
 * 日期格式化工具
 * @param {Date|string} date - 日期对象或日期字符串
 * @param {string} format - 格式模板，默认 'YYYY-MM-DD'
 * @returns {string} 格式化后的日期字符串
 */
export const formatDate = (date, format = 'YYYY-MM-DD') => {
  if (!date) return ''

  const d = new Date(date)
  if (isNaN(d.getTime())) return ''

  const pad = (num) => String(num).padStart(2, '0')

  const replacements = {
    YYYY: d.getFullYear(),
    MM: pad(d.getMonth() + 1),
    DD: pad(d.getDate()),
    HH: pad(d.getHours()),
    mm: pad(d.getMinutes()),
    ss: pad(d.getSeconds())
  }

  return format.replace(/YYYY|MM|DD|HH|mm|ss/g, (match) => replacements[match])
}

/**
 * 货币格式化工具
 * @param {number} value - 金额数值
 * @param {string} currency - 货币符号，默认 '¥'
 * @param {number} decimals - 小数位数，默认 2
 * @returns {string} 格式化后的货币字符串
 */
export const formatCurrency = (value, currency = '¥', decimals = 2) => {
  if (typeof value !== 'number' || isNaN(value)) return ''

  const formattedValue = value
    .toFixed(decimals)
    .replace(/\d(?=(\d{3})+\.)/g, '$&,')
  return `${currency} ${formattedValue}`
}

/**
 * 计算日期差值
 * @param {Date|string} startDate - 开始日期
 * @param {Date|string} endDate - 结束日期
 * @returns {number} 相差的天数
 */
export const dateDiffInDays = (startDate, endDate) => {
  const start = new Date(startDate)
  const end = new Date(endDate)
  const diffTime = Math.abs(end - start)
  return Math.ceil(diffTime / (1000 * 60 * 60 * 24))
}

/**
 * 深拷贝对象
 * @param {Object} obj - 需要拷贝的对象
 * @returns {Object} 深拷贝后的对象
 */
export const deepClone = (obj) => {
  if (obj === null || typeof obj !== 'object') return obj
  if (obj instanceof Date) return new Date(obj.getTime())
  if (obj instanceof RegExp) return new RegExp(obj)

  const clone = Array.isArray(obj) ? [] : {}
  for (const key in obj) {
    if (Object.hasOwnProperty.call(obj, key)) {
      clone[key] = deepClone(obj[key])
    }
  }
  return clone
}

/**
 * 生成唯一ID
 * @param {number} length - ID长度，默认 8
 * @returns {string} 唯一ID
 */
export const generateId = (length = 8) => {
  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
  let id = ''
  for (let i = 0; i < length; i++) {
    id += chars.charAt(Math.floor(Math.random() * chars.length))
  }
  return id
}

/**
 * 防抖函数
 * @param {Function} func - 需要防抖的函数
 * @param {number} wait - 等待时间，默认 300ms
 * @returns {Function} 防抖后的函数
 */
export const debounce = (func, wait = 300) => {
  let timeout
  return function (...args) {
    clearTimeout(timeout)
    timeout = setTimeout(() => func.apply(this, args), wait)
  }
}

/**
 * 节流函数
 * @param {Function} func - 需要节流的函数
 * @param {number} limit - 时间限制，默认 300ms
 * @returns {Function} 节流后的函数
 */
export const throttle = (func, limit = 300) => {
  let inThrottle
  return function (...args) {
    if (!inThrottle) {
      func.apply(this, args)
      inThrottle = true
      setTimeout(() => (inThrottle = false), limit)
    }
  }
}

/**
 * 判断是否为空值
 * @param {*} value - 需要判断的值
 * @returns {boolean} 是否为空
 */
export const isEmpty = (value) => {
  if (value === null || value === undefined) return true
  if (typeof value === 'string' && value.trim() === '') return true
  if (Array.isArray(value) && value.length === 0) return true
  if (typeof value === 'object' && Object.keys(value).length === 0) return true
  return false
}

/**
 * 将对象转换为查询字符串
 * @param {Object} params - 参数对象
 * @returns {string} 查询字符串
 */
export const toQueryString = (params) => {
  return Object.keys(params)
    .map(
      (key) => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`
    )
    .join('&')
}

/**
 * 从查询字符串解析对象
 * @param {string} queryString - 查询字符串
 * @returns {Object} 解析后的对象
 */
export const fromQueryString = (queryString) => {
  return Object.fromEntries(new URLSearchParams(queryString).entries())
}

/**
 * 复制文本到剪贴板
 * @param {string} text - 需要复制的文本
 * @returns {Promise<void>}
 */
export const copyToClipboard = (text) => {
  return navigator.clipboard.writeText(text)
}

/**
 * 生成随机颜色
 * @returns {string} 十六进制颜色值
 */
export const randomColor = () => {
  return `#${Math.floor(Math.random() * 0xffffff)
    .toString(16)
    .padStart(6, '0')}`
}

/**
 * 文件大小格式化
 * @param {number} bytes - 文件大小（字节）
 * @returns {string} 格式化后的文件大小
 */
export const formatFileSize = (bytes) => {
  if (bytes === 0) return '0 Bytes'
  const k = 1024
  const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']
  const i = Math.floor(Math.log(bytes) / Math.log(k))
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
}

/**
 * 生成UUID
 * @returns {string} UUID
 */
export const generateUUID = () => {
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
    const r = (Math.random() * 16) | 0
    const v = c === 'x' ? r : (r & 0x3) | 0x8
    return v.toString(16)
  })
}

/**
 * 将字符串转换为驼峰命名
 * @param {string} str - 需要转换的字符串
 * @returns {string} 驼峰命名字符串
 */
export const toCamelCase = (str) => {
  return str.replace(/[-_](.)/g, (_, char) => char.toUpperCase())
}

/**
 * 将字符串转换为短横线命名
 * @param {string} str - 需要转换的字符串
 * @returns {string} 短横线命名字符串
 */
export const toKebabCase = (str) => {
  return str
    .replace(/([A-Z])/g, '-$1')
    .toLowerCase()
    .replace(/^-/, '')
}

/**
 * 将字符串转换为标题格式
 * @param {string} str - 需要转换的字符串
 * @returns {string} 标题格式字符串
 */
export const toTitleCase = (str) => {
  return str.replace(
    /\w\S*/g,
    (txt) => txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase()
  )
}

/**
 * 将字符串转换为首字母大写
 * @param {string} str - 需要转换的字符串
 * @returns {string} 首字母大写字符串
 */
export const capitalize = (str) => {
  return str.charAt(0).toUpperCase() + str.slice(1)
}

/**
 * 将字符串转换为布尔值
 * @param {string} str - 需要转换的字符串
 * @returns {boolean} 转换后的布尔值
 */
export const toBoolean = (str) => {
  return str === 'true' || str === '1'
}

/**
 * 将布尔值转换为字符串
 * @param {boolean} bool - 需要转换的布尔值
 * @returns {string} 转换后的字符串
 */
export const fromBoolean = (bool) => {
  return bool ? 'true' : 'false'
}

/**
 * 将字符串转换为数字
 * @param {string} str - 需要转换的字符串
 * @returns {number} 转换后的数字
 */
export const toNumber = (str) => {
  return parseFloat(str)
}

/**
 * 将数字转换为字符串
 * @param {number} num - 需要转换的数字
 * @returns {string} 转换后的字符串
 */
export const fromNumber = (num) => {
  return num.toString()
}

/**
 * 将字符串转换为数组
 * @param {string} str - 需要转换的字符串
 * @param {string} separator - 分隔符，默认 ','
 * @returns {Array} 转换后的数组
 */
export const toArray = (str, separator = ',') => {
  return str.split(separator)
}

/**
 * 将数组转换为字符串
 * @param {Array} arr - 需要转换的数组
 * @param {string} separator - 分隔符，默认 ','
 * @returns {string} 转换后的字符串
 */
export const fromArray = (arr, separator = ',') => {
  return arr.join(separator)
}

/**
 * 将字符串转换为对象
 * @param {string} str - 需要转换的字符串
 * @returns {Object} 转换后的对象
 */
export const toObject = (str) => {
  return JSON.parse(str)
}

/**
 * 将对象转换为字符串
 * @param {Object} obj - 需要转换的对象
 * @returns {string} 转换后的字符串
 */
export const fromObject = (obj) => {
  return JSON.stringify(obj)
}

/**
 * 将字符串转换为日期
 * @param {string} str - 需要转换的字符串
 * @returns {Date} 转换后的日期
 */
export const toDate = (str) => {
  return new Date(str)
}

/**
 * 将日期转换为字符串
 * @param {Date} date - 需要转换的日期
 * @returns {string} 转换后的字符串
 */
export const fromDate = (date) => {
  return date.toISOString()
}

/**
 * 将字符串转换为时间戳
 * @param {string} str - 需要转换的字符串
 * @returns {number} 转换后的时间戳
 */
export const toTimestamp = (str) => {
  return new Date(str).getTime()
}

/**
 * 将时间戳转换为字符串
 * @param {number} timestamp - 需要转换的时间戳
 * @returns {string} 转换后的字符串
 */
export const fromTimestamp = (timestamp) => {
  return new Date(timestamp).toISOString()
}

/**
 * 将字符串转换为URL
 * @param {string} str - 需要转换的字符串
 * @returns {URL} 转换后的URL
 */
export const toURL = (str) => {
  return new URL(str)
}

/**
 * 将URL转换为字符串
 * @param {URL} url - 需要转换的URL
 * @returns {string} 转换后的字符串
 */
export const fromURL = (url) => {
  return url.toString()
}

/**
 * 将字符串转换为Blob
 * @param {string} str - 需要转换的字符串
 * @returns {Blob} 转换后的Blob
 */
export const toBlob = (str) => {
  return new Blob([str])
}

/**
 * 将Blob转换为字符串
 * @param {Blob} blob - 需要转换的Blob
 * @returns {string} 转换后的字符串
 */
export const fromBlob = (blob) => {
  return blob.text()
}

/**
 * 将字符串转换为ArrayBuffer
 * @param {string} str - 需要转换的字符串
 * @returns {ArrayBuffer} 转换后的ArrayBuffer
 */
export const toArrayBuffer = (str) => {
  return new TextEncoder().encode(str)
}

/**
 * 将ArrayBuffer转换为字符串
 * @param {ArrayBuffer} arrayBuffer - 需要转换的ArrayBuffer
 * @returns {string} 转换后的字符串
 */
export const fromArrayBuffer = (arrayBuffer) => {
  return new TextDecoder().decode(arrayBuffer)
}

/**
 * 将字符串转换为DataURL
 * @param {string} str - 需要转换的字符串
 * @returns {string} 转换后的DataURL
 */
export const toDataURL = (str) => {
  return `data:text/plain;base64,${btoa(str)}`
}

/**
 * 将DataURL转换为字符串
 * @param {string} dataURL - 需要转换的DataURL
 * @returns {string} 转换后的字符串
 */
export const fromDataURL = (dataURL) => {
  return atob(dataURL.split(',')[1])
}

/**
 * 将字符串转换为File
 * @param {string} str - 需要转换的字符串
 * @param {string} fileName - 文件名
 * @returns {File} 转换后的File
 */
export const toFile = (str, fileName) => {
  return new File([str], fileName)
}

/**
 * 将File转换为字符串
 * @param {File} file - 需要转换的File
 * @returns {string} 转换后的字符串
 */
export const fromFile = (file) => {
  return file.text()
}

/**
 * 将字符串转换为FormData
 * @param {string} str - 需要转换的字符串
 * @returns {FormData} 转换后的FormData
 */
export const toFormData = (str) => {
  const formData = new FormData()
  formData.append('data', str)
  return formData
}

/**
 * 将FormData转换为字符串
 * @param {FormData} formData - 需要转换的FormData
 * @returns {string} 转换后的字符串
 */
export const fromFormData = (formData) => {
  return formData.get('data')
}

/**
 * 将字符串转换为URLSearchParams
 * @param {string} str - 需要转换的字符串
 * @returns {URLSearchParams} 转换后的URLSearchParams
 */
export const toURLSearchParams = (str) => {
  return new URLSearchParams(str)
}

/**
 * 将URLSearchParams转换为字符串
 * @param {URLSearchParams} urlSearchParams - 需要转换的URLSearchParams
 * @returns {string} 转换后的字符串
 */
export const fromURLSearchParams = (urlSearchParams) => {
  return urlSearchParams.toString()
}

/**
 * 将字符串转换为ReadableStream
 * @param {string} str - 需要转换的字符串
 * @returns {ReadableStream} 转换后的ReadableStream
 */
export const toReadableStream = (str) => {
  return new ReadableStream({
    start(controller) {
      controller.enqueue(new TextEncoder().encode(str))
      controller.close()
    }
  })
}

/**
 * 将ReadableStream转换为字符串
 * @param {ReadableStream} readableStream - 需要转换的ReadableStream
 * @returns {string} 转换后的字符串
 */
export const fromReadableStream = (readableStream) => {
  return new Response(readableStream).text()
}

/**
 * 将字符串转换为Promise
 * @param {string} str - 需要转换的字符串
 * @returns {Promise<string>} 转换后的Promise
 */
export const toPromise = (str) => {
  return Promise.resolve(str)
}

/**
 * 将Promise转换为字符串
 * @param {Promise<string>} promise - 需要转换的Promise
 * @returns {string} 转换后的字符串
 */
export const fromPromise = (promise) => {
  return promise.then((str) => str)
}

/**
 * 将字符串转换为Observable
 * @param {string} str - 需要转换的字符串
 * @returns {Observable<string>} 转换后的Observable
 */
export const toObservable = (str) => {
  return new Observable((observer) => {
    observer.next(str)
    observer.complete()
  })
}

/**
 * 将Observable转换为字符串
 * @param {Observable<string>} observable - 需要转换的Observable
 * @returns {string} 转换后的字符串
 */
export const fromObservable = (observable) => {
  return observable.toPromise()
}

/**
 * 将字符串转换为Event
 * @param {string} str - 需要转换的字符串
 * @returns {Event} 转换后的Event
 */
export const toEvent = (str) => {
  return new Event(str)
}

/**
 * 将Event转换为字符串
 * @param {Event} event - 需要转换的Event
 * @returns {string} 转换后的字符串
 */
export const fromEvent = (event) => {
  return event.type
}

/**
 * 将字符串转换为CustomEvent
 * @param {string} str - 需要转换的字符串
 * @returns {CustomEvent} 转换后的CustomEvent
 */
export const toCustomEvent = (str) => {
  return new CustomEvent(str)
}

/**
 * 将CustomEvent转换为字符串
 * @param {CustomEvent} customEvent - 需要转换的CustomEvent
 * @returns {string} 转换后的字符串
 */
export const fromCustomEvent = (customEvent) => {
  return customEvent.type
}

/**
 * 将字符串转换为MessageEvent
 * @param {string} str - 需要转换的字符串
 * @returns {MessageEvent} 转换后的MessageEvent
 */
export const toMessageEvent = (str) => {
  return new MessageEvent(str)
}
